﻿using System;
using System.Configuration;
using System.Linq;

using ServiceStack.ServiceInterface;
using ServiceStack.Redis;
using ServiceStack.Redis.Generic;
using System.Security;
using System.Collections.Generic;
using GameTools;

namespace PuSuoPai
{
	public class PuSuoPaiService : Service
	{
		//================================= Login =================================
		public ConfirmRsp Post(CheckVersionRqt request)
		{
			ConfirmRsp rsp = new ConfirmRsp();

			try {
                using (var redis = RedisMgr.Instance.GetClient ())
				{
					string curVer = redis.Get<String>("Version");
                    if (curVer == null)
                    {
                        redis.Add<String>("Version", request.Version);
                        curVer = redis.Get<String>("Version");
                    }
					if (!curVer.Equals(request.Version))
					{
						rsp.Msg = "版本不正确,请到 www.pusuopai.com 下载最新版本!";
					}
					else
					{
						rsp.Msg = "ok";
					}
				}
			}
			catch (Exception e) {
				Log.WriteLog (e.Message);
			}

			return rsp;
		}

		public Player Post(LoginRqt request)
		{
			Player player = null;

			try {
				if (string.IsNullOrEmpty (request.Name) || string.IsNullOrEmpty (request.Passward))
					return null;

				using (var redis = RedisMgr.Instance.GetClient ())
				{
					string checkPassward = redis.GetValueFromHash ("User", request.Name);
					if (string.IsNullOrEmpty (checkPassward)) {
//						redis.SetEntryInHash ("User", request.Name, request.Passward);
//
//						player = new Player ();
//						player.Id = request.Name;
//						player.Name = request.Name;
//						player.Points = 2000;
//						player.IsVip = false;
//
//						IRedisTypedClient<Player> redisT = redis.As<Player> ();
//						redisT.StoreAsHash (player);
						return null;
					} else {
						if (!checkPassward.Equals (request.Passward))
							return null;

						IRedisTypedClient<Player> redisT = redis.As<Player> ();
						player = redisT.GetFromHash (request.Name);
					}
				}

				Console.WriteLine(DateTime.Now.ToString() + "$$" + string.Format("[{0}]登录成功！", request.Name));
			}
			catch (Exception e) {
				Log.WriteLog (e.Message);
			}

			return player;
		}

		public ConfirmRsp Post(CreaeteRqt request)
		{
			ConfirmRsp rsp = new ConfirmRsp();

			try {
				if (string.IsNullOrEmpty (request.Name) || string.IsNullOrEmpty (request.Passward))
					return null;

				using (var redis = RedisMgr.Instance.GetClient ())
				{
					string checkPassward = redis.GetValueFromHash ("User", request.Name);
					if (string.IsNullOrEmpty (checkPassward)) {
						redis.SetEntryInHash ("User", request.Name, request.Passward);

						Player player = new Player ();
						player.Id = request.Name;
						player.Name = request.Name;
						player.Points = 2000;
						player.IsVip = false;

						IRedisTypedClient<Player> redisT = redis.As<Player> ();
						redisT.StoreAsHash (player);

						rsp.Msg = "ok";

						Console.WriteLine(DateTime.Now.ToString() + "$$" + string.Format("[{0}]注册成功！", request.Name));
					} else {
						rsp.Msg = "此帐号已经被人使用！";
					}
				}
			}
			catch (Exception e) {
				Log.WriteLog (e.Message);
			}

			return rsp;
		}

		//================================= Nine Blocks =================================
		public const String Z_NB_EASY_RANKING = "NineBlocks:EasyRanking";
		public const String Z_NB_NORMAIL_RANKING = "NineBlocks:NormalRanking";
		public const String Z_NB_HARD_RANKING = "NineBlocks:HardRanking";

		public PlayerRecordNB Get(NBGetRecordRqt request)
		{
			PlayerRecordNB record = null;

			try {
				string strRanking = Z_NB_NORMAIL_RANKING;
	//			if (request.Diffcult == 0)
	//				strRanking = Z_NB_EASY_RANKING;
	//			else if (request.Diffcult == 2)
	//				strRanking = Z_NB_HARD_RANKING;

				record = new PlayerRecordNB ();
				record.TopRank = 0;
				record.TopScore = 0;
				record.TopGameScore = 0;

				using (var redis = RedisMgr.Instance.GetClient ())
				{
					if (redis.GetSortedSetCount (strRanking) > 0) {
						IDictionary<string, double> topScores = redis.GetRangeWithScoresFromSortedSet (strRanking, 0, 0);
						foreach (var info in topScores)
						{
							record.TopGameScore = (int)info.Value;
							break;
						}
					}

					if (redis.SortedSetContainsItem (strRanking, request.PlayerId)) {
						double score = redis.GetItemScoreInSortedSet (strRanking, request.PlayerId);
						long rank = redis.GetItemIndexInSortedSet (strRanking, request.PlayerId);

						record.TopRank = (int)rank;
						record.TopScore = (int)score;
					}
				}
			}
			catch (Exception e) {
				Log.WriteLog (e.Message);
			}

			return record;
		}

		public PlayerRecordNB POST(NBUpdateRecordRqt request)
		{
			PlayerRecordNB record = null;

			try {
				string strRanking = Z_NB_NORMAIL_RANKING;
	//			if (request.Diffcult == 0)
	//				strRanking = Z_NB_EASY_RANKING;
	//			else if (request.Diffcult == 2)
	//				strRanking = Z_NB_HARD_RANKING;

				record = new PlayerRecordNB ();
				record.TopRank = 0;
				record.TopScore = request.NewScore;
				record.TopGameScore = 0;

				using (var redis = RedisMgr.Instance.GetClient ())
				{
					if (redis.SortedSetContainsItem (strRanking, request.PlayerId)) {
						record.TopScore = (int)redis.GetItemScoreInSortedSet (strRanking, request.PlayerId);

						if (request.NewScore < record.TopScore) {
							if (redis.AddItemToSortedSet (strRanking, request.PlayerId, request.NewScore)) {
								record.TopScore = request.NewScore;
							}
						}
					} else {
						if (redis.AddItemToSortedSet (strRanking, request.PlayerId, request.NewScore)) {
							record.TopScore = request.NewScore;
						}
					}

					record.TopRank = (int)redis.GetItemIndexInSortedSet (strRanking, request.PlayerId);

					if (record.TopRank != 0) {
						IDictionary<string, double> topScores = redis.GetRangeWithScoresFromSortedSet (strRanking, 0, 0);
						foreach (var info in topScores) {
							record.TopGameScore = (int)info.Value;
							break;
						}
					} else {
						record.TopGameScore = record.TopScore;
					}

					// level diffcult
					string playerKey = RedisMgr.Instance.MakeHashId("Player", request.PlayerId);
					int curDiffcult = 0;
					string diffcult = redis.GetValueFromHash (playerKey, "NBDiffcult");
					if (!string.IsNullOrEmpty (diffcult))
						curDiffcult = int.Parse (diffcult);

					if (request.Diffcult == curDiffcult && request.NewScore == 1) {
						curDiffcult = curDiffcult + 1;
						redis.SetEntryInHash (playerKey, "NBDiffcult", curDiffcult.ToString ());
					}

					record.TopLevel = curDiffcult;

					// reward
					IRedisTypedClient<Player> redisT = redis.As<Player> ();
					Player player = redisT.GetFromHash (request.PlayerId);
					if (player == null)
						return null;

					player.Points += request.ResultPoint;
					if (player.Points < 0)
						player.Points = 0;

					record.RewardPoint = 0;
					if (request.RewardPoint > 0)
					{
						record.RewardPoint += request.RewardPoint;
					}

					if (request.Diffcult <= 2)
					{
						if (GameHelper.RandomSource.Next() % 10 == 0)
						{
							record.RewardPoint += 1;
						}
					}
					player.RewardPoints += record.RewardPoint;

					redisT.StoreAsHash(player);
				}
			}
			catch (Exception e) {
				Log.WriteLog (e.Message);
			}

			return record;
		}

		public PlayerPoint Post(NBForecastRqt request)
		{
			PlayerPoint rsp = null;

			try {
				if (string.IsNullOrEmpty (request.PlayerId))
					return null;

				using (var redis = RedisMgr.Instance.GetClient ())
				{
					IRedisTypedClient<Player> redisT = redis.As<Player> ();
					Player player = redisT.GetFromHash (request.PlayerId);
					if (player == null)
						return null;

					if (player.Points < 100)
						return null;

					player.Points -= 100;
					redisT.StoreAsHash(player);

					rsp = new PlayerPoint();
					rsp.CurPoint = player.Points;
				}

				Console.WriteLine(DateTime.Now.ToString() + "$$" + string.Format("[{0}]预测成功！", request.PlayerId));
			}
			catch (Exception e) {
				Log.WriteLog (e.Message);
			}

			return rsp;
		}

		public PlayerPoint Post(GetPointRqt request)
		{
			PlayerPoint rsp = null;

			try {
				if (string.IsNullOrEmpty (request.PlayerId))
					return null;

				using (var redis = RedisMgr.Instance.GetClient ())
				{
					IRedisTypedClient<Player> redisT = redis.As<Player> ();
					Player player = redisT.GetFromHash (request.PlayerId);
					if (player == null)
						return null;

//					player.Points += request.BuyPoints;
//					redisT.StoreAsHash(player);

					rsp = new PlayerPoint();
					rsp.CurPoint = player.Points;
				}
			}
			catch (Exception e) {
				Log.WriteLog (e.Message);
			}

			return rsp;
		}

		public ExchangeRsp Post(ExchangeRqt request)
		{
			ExchangeRsp rsp = null;

			try {
				if (string.IsNullOrEmpty (request.PlayerId))
					return null;

				if (request.Num <= 0)
					return null;

				using (var redis = RedisMgr.Instance.GetClient ())
				{
					IRedisTypedClient<Player> redisT = redis.As<Player> ();
					Player player = redisT.GetFromHash (request.PlayerId);
					if (player == null)
						return null;

					if (player.RewardPoints < request.Num)
						return null;

					player.RewardPoints -= request.Num;
					player.Points += request.Points;
					redisT.StoreAsHash(player);

					rsp = new ExchangeRsp();
					rsp.CurPoint = player.Points;
					rsp.RewardPoint = player.RewardPoints;
				}

				Console.WriteLine(DateTime.Now.ToString() + "$$" + string.Format("[{0}]兑换成功！", request.PlayerId));
			}
			catch (Exception e) {
				Log.WriteLog (e.Message);
			}

			return rsp;
		}

		public string Post(AlipayRqt request)
		{
			try {
				Log.WriteLog ("AlipayRqt success!  " + request.out_trade_no);
//				return "success";

				string ret = AlipayPlugin.CheckPay(request);

				if (!ret.Equals("success"))
					return ret;

				string serial = request.out_trade_no.Substring(request.out_trade_no.Length-7, 7);
				string playerId = request.out_trade_no.Substring(request.out_trade_no.Length-18, 11);

				using (var redis = RedisMgr.Instance.GetClient ())
				{
					if (redis.SetContainsItem("Serial", request.out_trade_no))
						return ret;

					int buyPoints = 0;
					if (!int.TryParse(serial, out buyPoints))
					{
						Log.WriteLog ("Serial: " + serial);
						return ret;
					}

					IRedisTypedClient<Player> redisT = redis.As<Player> ();
					Player player = redisT.GetFromHash (playerId);
					if (player == null)
					{
						Log.WriteLog ("Not found player!");
						return ret;
					}

					player.Points += buyPoints;
					redisT.StoreAsHash(player);

					redis.AddItemToSet("Serial", request.out_trade_no);
				}

				return ret;
			}
			catch (Exception e) {
				Log.WriteLog (e.Message);
			}

			return "success";
		}

		public CheckMatchCodeRsp Post(CheckMathCode request)
		{
			CheckMatchCodeRsp rsp = null;

			try {
				if (string.IsNullOrEmpty (request.PlayerId))
					return null;

				using (var redis = RedisMgr.Instance.GetClient ())
				{

					string hashId = "比赛代码:"+request.GameType;
					string matchId = redis.GetValueFromHash(hashId, request.Code);

//					if (string.IsNullOrEmpty(matchId))
//						return null;

					rsp = new CheckMatchCodeRsp();
					rsp.MatchId = 1;//int.Parse(matchId);
				}
			}
			catch (Exception e) {
				Log.WriteLog (e.Message);
			}

			return rsp;
		}

		static UInt32 sGuildEventId = 0;
		public GuildData.GuildEventInfo Post(SponsorGuildEvent request)
		{
			GuildData.GuildEventInfo rsp = null;

			if (string.IsNullOrEmpty (request.TargetGuildName))
				return null;

			try {
				using (var redis = RedisMgr.Instance.GetClient ())
				{
					IRedisTypedClient<Player> redisT = redis.As<Player> ();
					Player player = redisT.GetFromHash (request.PlayerId);
					if (player == null)
						return null;

					if (string.IsNullOrEmpty(player.GuildName))
						return null;

					// get guildInfo
					IRedisTypedClient<GuildData> redisGuild = redis.As<GuildData>();
					GuildData guild = redisGuild.GetFromHash(request.TargetGuildName);
					if (guild == null)
						return null;

					rsp = new GuildData.GuildEventInfo();
					rsp.GuildEventId = (++sGuildEventId).ToString();//DateTime.Now.Ticks.ToString() + GameHelper.RandomSource.Next(100000);
					rsp.GuildEvent = request.GuildEvent;
					rsp.SponsorId = player.Id;
					rsp.SponsorGuildName = player.GuildName;
					rsp.SponsorDate = DateTime.Now;

					if (guild.GuildEventInfoList == null)
					{
						guild.GuildEventInfoList = new List<GuildData.GuildEventInfo>();
					}

					guild.GuildEventInfoList.Add(rsp);
					redisGuild.StoreAsHash(guild);
				}
			}
			catch (Exception e) {
				Log.WriteLog (e.Message);
			}

			return rsp;
		}

		public GuildRoomData Post(AcceptGuildRoom request)
		{
			GuildRoomData rsp = null;

			if (string.IsNullOrEmpty (request.GuildEventId))
				return null;

			try {
				using (var redis = RedisMgr.Instance.GetClient ())
				{
					IRedisTypedClient<Player> redisT = redis.As<Player> ();
					Player player = redisT.GetFromHash (request.PlayerId);
					if (player == null)
						return null;

					if (string.IsNullOrEmpty(player.GuildName))
						return null;

					// get guildInfo
					IRedisTypedClient<GuildData> redisGuild = redis.As<GuildData>();
					GuildData guild = redisGuild.GetFromHash(player.GuildName);
					if (guild == null)
						return null;

					var eventInfos = guild.GuildEventInfoList.Where(x => x.GuildEventId.Equals(request.GuildEventId)).ToList();
					if (eventInfos == null || eventInfos.Count == 0)
						return null;

					var eventInfo = eventInfos[0];
					GuildData sponsorGuild = redisGuild.GetFromHash(eventInfo.SponsorGuildName);
					if (sponsorGuild == null)
						return null;

					rsp = new GuildRoomData();
					rsp.GuildRoomId = request.GuildEventId;
					rsp.SponsorId = player.Id;
					rsp.GuildEvent = eventInfo.GuildEvent;
					rsp.GuildName = sponsorGuild.Name;
					rsp.TargetGuildName = guild.Name;
					rsp.CreateDate = DateTime.Now;

					if (guild.GuildRoomList == null)
					{
						guild.GuildRoomList = new List<GuildRoomData>();
					}

					if (sponsorGuild.GuildRoomList == null)
					{
						sponsorGuild.GuildRoomList = new List<GuildRoomData>();
					}

					guild.GuildEventInfoList.Remove(eventInfo);
					guild.GuildRoomList.Add(rsp);
					sponsorGuild.GuildRoomList.Add(rsp);

					redisGuild.StoreAsHash(guild);
					redisGuild.StoreAsHash(sponsorGuild);
				}
			}
			catch (Exception e) {
				Log.WriteLog (e.Message);
			}

			return rsp;
		}

		public const string GuildListKey = "GuildList";
		public GetGuildListRsp Post(GetGuildList request)
		{ 
			GetGuildListRsp rsp = null;

			try {
				using (var redis = RedisMgr.Instance.GetClient ())
				{
					HashSet<string> guildList = redis.GetAllItemsFromSet(GuildListKey);
					rsp = new GetGuildListRsp();
					rsp.GuildList = new List<string>();
					foreach (var info in guildList)
					{
						rsp.GuildList.Add(info);
					}
				}
			}
			catch (Exception e) {
				Log.WriteLog (e.Message);
			}

			return rsp;
		}

		public GuildData Post(CreateGuild request)
		{
			GuildData rsp = null;

			try {
				if (string.IsNullOrEmpty (request.PlayerId))
					return null;

				using (var redis = RedisMgr.Instance.GetClient ())
				{
					if (redis.SetContainsItem(GuildListKey, request.GuildName))
						return null;

					IRedisTypedClient<Player> redisT = redis.As<Player> ();
					Player player = redisT.GetFromHash (request.PlayerId);
					if (player == null || !string.IsNullOrEmpty(player.GuildName))
						return null;

					if (player.Points < 1000)
						return null;

					player.Points -= 1000;

					GuildData guild = new GuildData();
					guild.Id = request.GuildName;
					guild.Name = request.GuildName;
					guild.LeaderName = player.Name;
					guild.MemberList = new List<string>();
					guild.MemberList.Add(player.Id);

					IRedisTypedClient<GuildData> redisGuild = redis.As<GuildData>();
					redisGuild.StoreAsHash(guild);
					redis.AddItemToSet(GuildListKey, request.GuildName);
					redisT.StoreAsHash(player);

					rsp = guild;
				}
			}
			catch (Exception e) {
				Log.WriteLog (e.Message);
			}

			return rsp;
		}

		public GuildData Post(JoinGuild request)
		{
			GuildData rsp = null;

			try {
				if (string.IsNullOrEmpty (request.PlayerId))
					return null;

				if (string.IsNullOrEmpty(request.GuildName))
					return null;

				using (var redis = RedisMgr.Instance.GetClient ())
				{
					if (!redis.SetContainsItem(GuildListKey, request.GuildName))
						return null;

					IRedisTypedClient<Player> redisT = redis.As<Player> ();
					Player player = redisT.GetFromHash (request.PlayerId);
					if (player == null || !string.IsNullOrEmpty(player.GuildName))
						return null;

					// get guildInfo
					IRedisTypedClient<GuildData> redisGuild = redis.As<GuildData>();
					GuildData guild = redisGuild.GetFromHash(request.GuildName);

					// do join guild
					player.GuildName = guild.Name;
					guild.MemberList.Add(player.Id);

					redisT.StoreAsHash(player);
					redisGuild.StoreAsHash(guild);

					rsp = guild;
				}
			}
			catch (Exception e) {
				Log.WriteLog (e.Message);
			}

			return rsp;
		}

		public Player Post(QuitGuild request)
		{
			try {
				if (string.IsNullOrEmpty (request.PlayerId))
					return null;

				using (var redis = RedisMgr.Instance.GetClient ())
				{
					IRedisTypedClient<Player> redisT = redis.As<Player> ();
					Player player = redisT.GetFromHash (request.PlayerId);
					if (player == null)
						return null;

					if (string.IsNullOrEmpty(player.GuildName))
						return player;

					// get guildInfo
					IRedisTypedClient<GuildData> redisGuild = redis.As<GuildData>();
					GuildData guild = redisGuild.GetFromHash(player.GuildName);
					if (guild != null)
					{
						guild.MemberList.Remove(player.Name);
						redisGuild.StoreAsHash(guild);
					}

					// do quit guild
					player.GuildName = "";
					redisT.StoreAsHash(player);

					return player;
				}
			}
			catch (Exception e) {
				Log.WriteLog (e.Message);

				return null;
			}
		}

		public GuildData Post(GetGuild request)
		{
			GuildData rsp = null;

			try {
				if (string.IsNullOrEmpty(request.GuildName))
					return null;

				using (var redis = RedisMgr.Instance.GetClient ())
				{
					// get guildInfo
					IRedisTypedClient<GuildData> redisGuild = redis.As<GuildData>();
					GuildData guild = redisGuild.GetFromHash(request.GuildName);

					return guild;
				}
			}
			catch (Exception e) {
				Log.WriteLog (e.Message);
			}

			return rsp;
		}

		//================= Jing Wu =====================
		public ConfirmRsp Post(JingWu_DianZan request)
		{

			try {
				using (var redis = RedisMgr.Instance.GetClient ())
				{
					string id = request.ContextIndices;
					var score = redis.IncrementItemInSortedSet("JingWu_DianZan", id, 1);

					return new ConfirmRsp() { Msg = ((int)score).ToString() };
				}
			}
			catch (Exception e) {
				Log.WriteLog (e.Message);
			}

			return new ConfirmRsp() { Msg = "faild" };
		}

		public PlayerPoint Post(JingWu_AddPoints request)
		{

			try {
				using (var redis = RedisMgr.Instance.GetClient ())
				{
					if (string.IsNullOrEmpty (request.PlayerId))
						return null;

					IRedisTypedClient<Player> redisT = redis.As<Player> ();
					Player player = redisT.GetFromHash (request.PlayerId);
					if (player == null)
						return null;
						
					if (request.Points < 0)
						return null;

					player.Points += request.Points;
					redisT.StoreAsHash(player);

					return new PlayerPoint() { CurPoint = player.Points };
				}
			}
			catch (Exception e) {
				Log.WriteLog (e.Message);
			}

			return null;
		}

		//===============================================
	}
}

